/*
* ============================================================================
*  Name        : sea_meta_system.h
*  Part of     : Finite state machine utilities
*  Description : Meta system definition
*  Version     : %version: %
*  
*
* ============================================================================
*/

#if !defined( __sm_meta_system__ )
#define __sm_meta_system__

#include "sea_platform.h"

/**
 * @file sea_meta_system.h
 * @brief Meta system keeps all the records( @ref sea::MetaSystemRegistryEntry ) of classes and their state machines bodies <br>
 * in global repository - @ref sea::GlobalMetaSystemRegistry
 * { class_name, statemachine_body }
 *
 * @ingroup StateMachineFramework
 */
namespace sea
{
    class MetaSystemRegistryEntry;

    /**
     * @class GlobalMetaSystemRegistry
     * @brief Global meta system registry, where all state machines have to be registered with. It contains
     * mapping of state machine name with the state machine registry entry. \b INTERNAL \b API. 
     *
     * @ingroup StateMachineFramework
     */
    class GlobalMetaSystemRegistry
    {
        friend class MetaSystem;
        friend class MetaAction;
        friend class MetaEvent;
        friend class Parser;

    public:
        typedef map< string, sea::ref< MetaSystemRegistryEntry > > MetaRegistryEntryType;

        static MetaRegistryEntryType& get( )
        {
            if ( m_meta_system_registry == NULL )
            {
                m_lock.enter( );

                if ( m_meta_system_registry == NULL )
                {
                    MetaRegistryEntryType* registry = new MetaRegistryEntryType;
                    m_meta_system_registry = registry;
                }
                m_lock.leave( );
            }
            return *m_meta_system_registry;
        }

    private:
        static MetaRegistryEntryType* m_meta_system_registry; ///< Mapping Class name-> state 
                                                              ///< machine registry
        static OsMutex m_lock;
    };

    /**
     * @class MetaSystem
     * @brief Meta system registry service. Purpose is to create 
     * new entry in the global meta system registry. \b INTERNAL \b API. 
     *
     * @ingroup StateMachineFramework
     */
    class MetaSystem
    {
        friend class Engine;
        friend class StateMachine;
        friend class SystemStateMachine;
        friend class MetaAction;
        friend class MetaEvent;

    private:

        MetaSystem( String class_name )
        {
            if ( class_name == "" )
            {
                return;
            }
            const char* name = NULL;
            for ( const char* temp = strchr( class_name.c_str( ), ':' ); 
                  temp; 
                  temp = strchr( temp + 2, ':' ) )
            {
                name = temp;
            }

            if ( name )
            {
                m_registry_entry = insert( string( name + 2 ) );
            }
            else
            {
                name = class_name.c_str( );
                if ( strchr( name, ' ' ) )
                {
                    name += 6;
                }
                m_registry_entry = insert( string( name ) );
            }
        }

        static sea::ref< MetaSystemRegistryEntry > insert( String name );
        static void destroy( );
        MetaSystemRegistryEntry* registry( ) { return m_registry_entry.get( ); }

    private:
        sea::ref< MetaSystemRegistryEntry > m_registry_entry;
    };
}

#endif // #if !defined( __sm_meta_system__ )

